﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.TeamFoundation.Server;
using System.Threading;

namespace FunctionPoint.Services
{
    internal class MemberReader : IComparable
    {

        private Identity _identity;
        private IGroupSecurityService _gss;
        private List<string> _memberNames;

        public Identity Identity
        {
            get { return _identity; }
        }

        public List<string> MemberNames
        {
            get { return _memberNames; }
        }
        public IGroupSecurityService Gss
        {
            get { return _gss; }
        }

        public MemberReader(Identity identity, IGroupSecurityService gss)
        {
            _memberNames = new List<String>();
            _identity = identity;
            _gss = gss;
        }

        public void Read()
        {
            Identity directMembers = _gss.ReadIdentity(SearchFactor.Sid, _identity.Sid, QueryMembership.Expanded);

            ManualResetEvent[] doneEvents = new ManualResetEvent[directMembers.Members.GetLength(0)];
            IdentityReader[] readers = new IdentityReader[doneEvents.Length];
            int i = 0;
            foreach (string memberSid in directMembers.Members)
            {
                doneEvents[i] = new ManualResetEvent(false);
                IdentityReader reader = new IdentityReader(memberSid, this, doneEvents[i]);
                readers[i] = reader;
                ThreadPool.QueueUserWorkItem(reader.ThreadPoolCallback);
                i++;
            }

            //can only wait for 64 at a time
            for (int j = 0; j < doneEvents.Length; j += 64)
            {
                int max = Math.Min((j + 64), doneEvents.Length);
                ManualResetEvent[] partEvents = new ManualResetEvent[(max - j)];
                Array.Copy(doneEvents, j, partEvents, 0, (max - j));
                WaitHandle.WaitAll(partEvents);
            }

        }

        private class IdentityReader
        {
            private String _memberSid;
            private MemberReader _memberReader;
            private ManualResetEvent _doneEvent;
            public string MemberSid
            {
                get { return _memberSid; }
            }

            public ManualResetEvent DoneEvent
            {
                get
                {
                    return _doneEvent;
                }
            }


            public IdentityReader(string memberSid, MemberReader memberReader, ManualResetEvent doneEvent)
            {
                _memberSid = memberSid;
                _memberReader = memberReader;
                _doneEvent = doneEvent;
            }

            public void ThreadPoolCallback(Object threadContext)
            {
                Identity member = _memberReader.Gss.ReadIdentity(SearchFactor.Sid, _memberSid, QueryMembership.None);

                if (!member.SecurityGroup && member.Type != IdentityType.WindowsGroup
                    && member.Type != IdentityType.ApplicationGroup)
                {
                    if (!_memberReader.MemberNames.Contains(member.DisplayName))
                    {
                        lock (_memberReader.MemberNames)
                        {
                            if (!_memberReader.MemberNames.Contains(member.DisplayName))
                                _memberReader.MemberNames.Add(member.DisplayName);
                        }
                    }

                }

                _doneEvent.Set();
            }
        }

        #region IComparable Members

        public int CompareTo(object obj)
        {
            if (obj is MemberReader)
            {
                MemberReader mr2 = (MemberReader)obj;
                return Identity.DisplayName.CompareTo(mr2.Identity.DisplayName);
            }
            else
                throw new ArgumentException("Object is not a MemberReader.");

        }

        #endregion
    }
}
